package com.gulimall.product.service.impl;

import com.common.constant.ProductConstant;
import com.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.gulimall.product.dao.AttrGroupDao;
import com.gulimall.product.dao.CategoryDao;
import com.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.gulimall.product.entity.AttrGroupEntity;
import com.gulimall.product.entity.CategoryEntity;
import com.gulimall.product.vo.AttrVo;
import com.gulimall.product.vo.AttrVoRes;
import com.gulimall.product.vo.GroupWithAttrVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.utils.PageUtils;
import com.common.utils.Query;

import com.gulimall.product.dao.AttrDao;
import com.gulimall.product.entity.AttrEntity;
import com.gulimall.product.service.AttrService;

import javax.annotation.Resource;

@Slf4j
@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
    @Resource
    AttrDao attrDao;
    @Resource
    CategoryDao categoryDao;
    @Resource
    AttrGroupDao attrGroupDao;
    @Resource
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;
    @Resource
    private CategoryServiceImpl categoryServiceImpl;

    @Override
    public PageUtils queryPage(String type,Long cateLogId, Map<String, Object> params) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("attr_type","base".equals(type)?ProductConstant.AttrTypeEnum.ATTR_BASE.getCode():ProductConstant.AttrTypeEnum.ATTR_SALE.getCode());
        if(cateLogId != 0){
            queryWrapper.eq("catelog_id",cateLogId);
        }

        String key = (String) params.get("key");
        if(StringUtils.isNotBlank(key)){
            queryWrapper.eq("attr_id",key).or().like("attr_name",key);
        }

        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                queryWrapper
        );
        PageUtils pageUtils = new PageUtils(page);


        // 对返回的数据进行设置，改成前端所需的格式返回
        List<AttrEntity> attrEntityList = page.getRecords();
        List<AttrVoRes> attrVoResList = attrEntityList.stream().map(attrEntity -> {
            AttrVoRes attrVoRes = new AttrVoRes();
            BeanUtils.copyProperties(attrEntity, attrVoRes);
            // 依次查询对返回的属性进行填充
            CategoryEntity categoryEntity = categoryDao.selectById(attrVoRes.getCatelogId());
            attrVoRes.setCatelogName(categoryEntity.getName());
            if("base".equals(type)) {
                // 如果是规格参数才进行 groupName 的查询
                AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVoRes.getAttrId()));
                // 如果不存在关联数据那么就跳过
                if (relationEntity != null) {
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                    attrVoRes.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
            return attrVoRes;
        }).collect(Collectors.toList());
        pageUtils.setList(attrVoResList);

        return pageUtils;
    }

    // 缓存key ：attrInfo:8
    @Cacheable(value="attr",key ="'attrInfo:'+#root.args[0]")
    @Override
    public AttrVoRes queryAttrInfo(Long attrId) {
        AttrVoRes attrVoRes = new AttrVoRes();
        AttrEntity attrEntity = baseMapper.selectById(attrId);
        BeanUtils.copyProperties(attrEntity, attrVoRes);
        AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
        if(relationEntity != null){
            attrVoRes.setAttrGroupId(relationEntity.getAttrGroupId());
        }
        attrVoRes.setCatelogPath(categoryServiceImpl.getFatherIds(attrEntity.getCatelogId()));
        return attrVoRes;
    }

    /**
     * 更新属性以及其关联分组的关系数据
     * @param attrVo
     */
    @Override
    public void updateDetail(AttrVo attrVo) {
        // 1、修改属性信息
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        this.updateById(attrEntity);
        // 2、如果传来的对象包含分组ID，那么说明也修改了分组           并且是普通属性，那么就进行分组数据的添加/修改
        if(attrVo.getAttrGroupId() != null && attrVo.getAttrType().equals(ProductConstant.AttrTypeEnum.ATTR_BASE.getCode())){
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            int i = attrAttrgroupRelationDao.update(relationEntity, new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
            // 如果 i == 0说明原本不存在，那么就进行新增操作
            if(i == 0){
                relationEntity.setAttrId(attrVo.getAttrId());
                attrAttrgroupRelationDao.insert(relationEntity);
            }
        }
    }

    /**
     * 添加属性以及分组信息
     * @param attrVo
     */
    @Override
    public void saveDetail(AttrVo attrVo) {
        // 1、进行 attr参数添加
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        baseMapper.insert(attrEntity);
        // 2、进行 attr_group 关联数据添加
        if(attrVo.getAttrGroupId() != null){
            // 如果设置了分组再添加
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
        }
    }

    @Override
    public List<AttrEntity> queryRelationList(Long attrGroupId) {
        return attrDao.selectAttrListByGroupId(attrGroupId);
    }

    @Override
    public PageUtils queryNoRelationList(Map<String, Object> params, Long attrGroupId) {
        // 1、找出当前分类下已经关联的所有属性ID集合
        // 1.1 找出当前分组对应的分类ID
        Long cateLogId = attrGroupDao.selectById(attrGroupId).getCatelogId();
        // 1.2 通过分类ID找出当前分类下所有分组
        List<AttrGroupEntity> attrGroupEntityList = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", cateLogId));
        List<Long> attrGroupIdList = attrGroupEntityList.stream().map(AttrGroupEntity::getAttrGroupId).collect(Collectors.toList());
        // 1.3 根据分组找出所有已关联的属性ID集合
        List<Long> attrIdList = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", attrGroupIdList))
                .stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());

        // 2、设置条件（1、属性不在已关联属性ID集合中，2、属性所属分类必须等于分组对应分类 3、如果参数有 like 还需要添加模糊判断）
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        // 2.1
        if(attrIdList.size() != 0){
            queryWrapper.notIn("attr_id",attrIdList);
        }
        // 2.2
        queryWrapper.eq("catelog_id",cateLogId);
        // 2.3
        String key = (String) params.get("key");
        if(StringUtils.isNotBlank(key)){
            queryWrapper.like("attr_name",key);
        }

        // 3、得出结果
        IPage<AttrEntity> page = page(new Query<AttrEntity>().getPage(params),
                queryWrapper);
        return new PageUtils(page);
    }

    @Override
    public List<GroupWithAttrVo> getGroupWithAttr(Long cateId) {
        // 获取当前分类下所有分组对象集合
        List<AttrGroupEntity> attrGroupEntityList = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", cateId));
        // 开始遍历，拼接成需要的实体类
        List<GroupWithAttrVo> groupWithAttrVoList = attrGroupEntityList.stream().map(attrGroupEntity -> {
            GroupWithAttrVo groupWithAttrVo = new GroupWithAttrVo();
            // 进行分组属性填充
            BeanUtils.copyProperties(attrGroupEntity, groupWithAttrVo);
            //根据分组ID找到绑定的关系数据
            List<AttrAttrgroupRelationEntity> relationEntityList = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrGroupEntity.getAttrGroupId()));
            // 通过关系数据ID找到对应属性ID集合
            List<Long> attrIdList = relationEntityList.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
            // 通过属性ID找到属性对象，返回
            if(attrIdList.size() > 0){
                List<AttrEntity> attrEntityList = attrDao.selectBatchIds(attrIdList);
                groupWithAttrVo.setAttrs(attrEntityList);
            }
            return groupWithAttrVo;
        }).collect(Collectors.toList());
        return groupWithAttrVoList;
    }

}